/******************************************************************************* * Copyright (c) 2011, 2016 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.browser; import java.nio.charset.*; import java.util.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.cocoa.*; import org.eclipse.swt.layout.*; import org.eclipse.swt.widgets.*; @SuppressWarnings({"rawtypes"}) class WebKit extends WebBrowser { WebView webView; WebPreferences preferences; SWTWebViewDelegate delegate; boolean loadingText, untrustedText; String lastHoveredLinkURL, lastNavigateURL; String html; long /*int*/ identifier; int resourceCount; String url = ""; //$NON-NLS-1$ Point location; Point size; boolean statusBar = true, toolBar = true, ignoreDispose; int lastMouseMoveX, lastMouseMoveY; //TEMPORARY CODE // boolean doit; static long /*int*/ delegateClass; static boolean Initialized; // the following Callbacks are never freed static Callback Callback3, Callback4, Callback5, Callback6, Callback7; static final int MIN_SIZE = 16; static final int MAX_PROGRESS = 100; static final String WebElementLinkURLKey = "WebElementLinkURL"; //$NON-NLS-1$ static final String AGENT_STRING = "Safari/522.0"; /* Safari version on OSX 10.5 initial release */ //$NON-NLS-1$ static final String URI_FILEROOT = "file:///"; //$NON-NLS-1$ static final String PROTOCOL_FILE = "file://"; //$NON-NLS-1$ static final String PROTOCOL_HTTP = "http://"; //$NON-NLS-1$ static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ static final String HEADER_SETCOOKIE = "Set-Cookie"; //$NON-NLS-1$ static final String POST = "POST"; //$NON-NLS-1$ static final String USER_AGENT = "user-agent"; //$NON-NLS-1$ static final String ADD_WIDGET_KEY = "org.eclipse.swt.internal.addWidget"; //$NON-NLS-1$ static final String WEBKIT_EVENTS_FIX_KEY = "org.eclipse.swt.internal.webKitEventsFix"; //$NON-NLS-1$ static final byte[] SWT_OBJECT = {'S', 'W', 'T', '_', 'O', 'B', 'J', 'E', 'C', 'T', '\0'}; /* event strings */ static final String DOMEVENT_KEYUP = "keyup"; //$NON-NLS-1$ static final String DOMEVENT_KEYDOWN = "keydown"; //$NON-NLS-1$ static final String DOMEVENT_MOUSEDOWN = "mousedown"; //$NON-NLS-1$ static final String DOMEVENT_MOUSEUP = "mouseup"; //$NON-NLS-1$ static final String DOMEVENT_MOUSEMOVE = "mousemove"; //$NON-NLS-1$ static final String DOMEVENT_MOUSEWHEEL = "mousewheel"; //$NON-NLS-1$ static { NativeClearSessions = () -> { NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage(); NSArray cookies = storage.cookies(); int count = (int)/*64*/cookies.count (); for (int i = 0; i < count; i++) { NSHTTPCookie cookie = new NSHTTPCookie(cookies.objectAtIndex(i)); if (cookie.isSessionOnly()) { storage.deleteCookie(cookie); } } }; NativeGetCookie = () -> { NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage (); NSURL url = NSURL.URLWithString (NSString.stringWith (CookieUrl)); NSArray cookies = storage.cookiesForURL (url); int count = (int)/*64*/cookies.count (); if (count == 0) return; NSString name = NSString.stringWith (CookieName); for (int i = 0; i < count; i++) { NSHTTPCookie current = new NSHTTPCookie (cookies.objectAtIndex (i)); if (current.name ().compare (name) == OS.NSOrderedSame) { CookieValue = current.value ().getString (); return; } } }; NativeSetCookie = () -> { NSURL url = NSURL.URLWithString (NSString.stringWith (CookieUrl)); NSMutableDictionary headers = NSMutableDictionary.dictionaryWithCapacity (1); headers.setValue (NSString.stringWith (CookieValue), NSString.stringWith (HEADER_SETCOOKIE)); NSArray cookies = NSHTTPCookie.cookiesWithResponseHeaderFields (headers, url); if (cookies.count () == 0) return; NSHTTPCookieStorage storage = NSHTTPCookieStorage.sharedHTTPCookieStorage (); NSHTTPCookie cookie = new NSHTTPCookie (cookies.objectAtIndex (0)); storage.setCookie (cookie); CookieResult = true; }; if (NativePendingCookies != null) { SetPendingCookies (NativePendingCookies); } NativePendingCookies = null; } @Override public void create (Composite parent, int style) { if (delegateClass == 0) { Class webKitClass = this.getClass(); Callback3 = new Callback(webKitClass, "browserProc", 3); //$NON-NLS-1$ long /*int*/ proc3 = Callback3.getAddress(); if (proc3 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); Callback4 = new Callback(webKitClass, "browserProc", 4); //$NON-NLS-1$ long /*int*/ proc4 = Callback4.getAddress(); if (proc4 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); Callback5 = new Callback(webKitClass, "browserProc", 5); //$NON-NLS-1$ long /*int*/ proc5 = Callback5.getAddress(); if (proc5 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); Callback6 = new Callback(webKitClass, "browserProc", 6); //$NON-NLS-1$ long /*int*/ proc6 = Callback6.getAddress(); if (proc6 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); Callback7 = new Callback(webKitClass, "browserProc", 7); //$NON-NLS-1$ long /*int*/ proc7 = Callback7.getAddress(); if (proc7 == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); long /*int*/ setFrameProc = OS.CALLBACK_webView_setFrame_(proc4); if (setFrameProc == 0) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS); String className = "SWTWebViewDelegate"; //$NON-NLS-1$ byte[] types = {'*','\0'}; int size = C.PTR_SIZEOF, align = C.PTR_SIZEOF == 4 ? 2 : 3; delegateClass = OS.objc_allocateClassPair (OS.class_NSObject, className, 0); OS.class_addIvar(delegateClass, SWT_OBJECT, size, (byte)align, types); OS.class_addMethod(delegateClass, OS.sel_webView_didChangeLocationWithinPageForFrame_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_didFailProvisionalLoadWithError_forFrame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_didFinishLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_didReceiveTitle_forFrame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_didStartProvisionalLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_didCommitLoadForFrame_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didFinishLoadingFromDataSource_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didReceiveAuthenticationChallenge_fromDataSource_, proc6, "@:@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_resource_didFailLoadingWithError_fromDataSource_, proc6, "@:@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_identifierForInitialRequest_fromDataSource_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_resource_willSendRequest_redirectResponse_fromDataSource_, proc7, "@:@@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_createWebViewWithRequest_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webViewShow_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webViewClose_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_contextMenuItemsForElement_defaultMenuItems_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_setStatusBarVisible_, proc4, "@:@B"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_setResizable_, proc4, "@:@B"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_setToolbarsVisible_, proc4, "@:@B"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_setStatusText_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webViewFocus_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webViewUnfocus_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptAlertPanelWithMessage_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptAlertPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptConfirmPanelWithMessage_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runJavaScriptConfirmPanelWithMessage_initiatedByFrame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_runOpenPanelForFileButtonWithResultListener_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_mouseDidMoveOverElement_modifierFlags_, proc5, "@:@@I"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_printFrameView_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForMIMEType_request_frame_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForNavigationAction_request_frame_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener_, proc7, "@:@@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_unableToImplementPolicyWithError_frame_, proc5, "@:@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_download_decideDestinationWithSuggestedFilename_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_handleEvent_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_setFrame_, setFrameProc, "@:@{NSRect}"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_webView_windowScriptObjectAvailable_, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_callJava, proc6, "@:@@@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_callRunBeforeUnloadConfirmPanelWithMessage, proc4, "@:@@"); //$NON-NLS-1$ OS.class_addMethod(delegateClass, OS.sel_createPanelDidEnd, proc5, "@:@@@"); //$NON-NLS-1$ OS.objc_registerClassPair(delegateClass); long /*int*/ metaClass = OS.objc_getMetaClass (className); OS.class_addMethod(metaClass, OS.sel_isSelectorExcludedFromWebScript_, proc3, "@:@"); //$NON-NLS-1$ OS.class_addMethod(metaClass, OS.sel_webScriptNameForSelector_, proc3, "@:@"); //$NON-NLS-1$ } /* * Override the default event mechanism to not send key events so * that the browser can send them by listening to the DOM instead. */ browser.setData(WEBKIT_EVENTS_FIX_KEY); WebView webView = (WebView)new WebView().alloc(); if (webView == null) SWT.error(SWT.ERROR_NO_HANDLES); webView.initWithFrame(browser.view.frame(), null, null); webView.setAutoresizingMask(OS.NSViewWidthSizable | OS.NSViewHeightSizable); if (webView.respondsToSelector(OS.sel__setDashboardBehavior)) { OS.objc_msgSend(webView.id, OS.sel__setDashboardBehavior, 2, 1); } final SWTWebViewDelegate delegate = (SWTWebViewDelegate)new SWTWebViewDelegate().alloc().init(); Display display = browser.getDisplay(); display.setData(ADD_WIDGET_KEY, new Object[] {delegate, browser}); this.delegate = delegate; this.webView = webView; browser.view.addSubview(webView); Listener listener = e -> { switch (e.type) { case SWT.FocusIn: WebKit.this.webView.window().makeFirstResponder(WebKit.this.webView); break; case SWT.Dispose: { /* make this handler run after other dispose listeners */ if (ignoreDispose) { ignoreDispose = false; break; } ignoreDispose = true; browser.notifyListeners (e.type, e); e.type = SWT.NONE; /* Browser could have been disposed by one of the Dispose listeners */ if (!browser.isDisposed()) { /* invoke onbeforeunload handlers */ if (!browser.isClosing) { close (false); } e.display.setData(ADD_WIDGET_KEY, new Object[] {delegate, null}); } WebKit.this.webView.setFrameLoadDelegate(null); WebKit.this.webView.setResourceLoadDelegate(null); WebKit.this.webView.setUIDelegate(null); WebKit.this.webView.setPolicyDelegate(null); WebKit.this.webView.setDownloadDelegate(null); WebKit.this.webView.release(); WebKit.this.webView = null; WebKit.this.delegate.release(); WebKit.this.delegate = null; html = null; lastHoveredLinkURL = lastNavigateURL = null; Iterator<BrowserFunction> elements = functions.values().iterator (); while (elements.hasNext ()) { elements.next ().dispose (false); } functions = null; if (preferences != null) preferences.release (); preferences = null; break; } } }; browser.addListener(SWT.Dispose, listener); browser.addListener(SWT.KeyDown, listener); /* needed for tabbing into the Browser */ browser.addListener(SWT.FocusIn, listener); webView.setFrameLoadDelegate(delegate); webView.setResourceLoadDelegate(delegate); webView.setUIDelegate(delegate); webView.setPolicyDelegate(delegate); webView.setDownloadDelegate(delegate); webView.setApplicationNameForUserAgent(NSString.stringWith(AGENT_STRING)); if (!Initialized) { Initialized = true; /* disable applets */ WebPreferences.standardPreferences().setJavaEnabled(false); } } @Override public boolean back() { html = null; return webView.goBack(); } static long /*int*/ browserProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0) { if (id == delegateClass) { if (sel == OS.sel_isSelectorExcludedFromWebScript_) { return isSelectorExcludedFromWebScript (arg0) ? 1 : 0; } else if (sel == OS.sel_webScriptNameForSelector_) { return webScriptNameForSelector (arg0); } } Display d = Display.getCurrent(); if (d == null || d.isDisposed()) return 0; Widget widget = d.findWidget(id); if (widget == null) return 0; WebKit webKit = (WebKit)((Browser)widget).webBrowser; if (sel == OS.sel_webViewShow_) { webKit.webViewShow(arg0); } else if (sel == OS.sel_webViewClose_) { webKit.webViewClose(arg0); } else if (sel == OS.sel_webViewFocus_) { webKit.webViewFocus(arg0); } else if (sel == OS.sel_webViewUnfocus_) { webKit.webViewUnfocus(arg0); } else if (sel == OS.sel_handleEvent_) { webKit.handleEvent(arg0); } return 0; } static long /*int*/ browserProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1) { Display d = Display.getCurrent(); if (d == null || d.isDisposed()) return 0; Widget widget = d.findWidget(id); if (widget == null) return 0; WebKit webKit = (WebKit)((Browser)widget).webBrowser; if (sel == OS.sel_webView_didChangeLocationWithinPageForFrame_) { webKit.webView_didChangeLocationWithinPageForFrame(arg0, arg1); } else if (sel == OS.sel_webView_didFinishLoadForFrame_) { webKit.webView_didFinishLoadForFrame(arg0, arg1); } else if (sel == OS.sel_webView_didStartProvisionalLoadForFrame_) { webKit.webView_didStartProvisionalLoadForFrame(arg0, arg1); } else if (sel == OS.sel_webView_didCommitLoadForFrame_) { webKit.webView_didCommitLoadForFrame(arg0, arg1); } else if (sel == OS.sel_webView_setFrame_) { webKit.webView_setFrame(arg0, arg1); } else if (sel == OS.sel_webView_createWebViewWithRequest_) { return webKit.webView_createWebViewWithRequest(arg0, arg1); } else if (sel == OS.sel_webView_setStatusBarVisible_) { webKit.webView_setStatusBarVisible(arg0, arg1 != 0); } else if (sel == OS.sel_webView_setResizable_) { webKit.webView_setResizable(arg0, arg1 != 0); } else if (sel == OS.sel_webView_setStatusText_) { webKit.webView_setStatusText(arg0, arg1); } else if (sel == OS.sel_webView_setToolbarsVisible_) { webKit.webView_setToolbarsVisible(arg0, arg1 != 0); } else if (sel == OS.sel_webView_runJavaScriptAlertPanelWithMessage_) { webKit.webView_runJavaScriptAlertPanelWithMessage(arg0, arg1); } else if (sel == OS.sel_webView_runJavaScriptConfirmPanelWithMessage_) { return webKit.webView_runJavaScriptConfirmPanelWithMessage(arg0, arg1); } else if (sel == OS.sel_webView_runOpenPanelForFileButtonWithResultListener_) { webKit.webView_runOpenPanelForFileButtonWithResultListener(arg0, arg1); } else if (sel == OS.sel_download_decideDestinationWithSuggestedFilename_) { webKit.download_decideDestinationWithSuggestedFilename(arg0, arg1); } else if (sel == OS.sel_webView_printFrameView_) { webKit.webView_printFrameView(arg0, arg1); } else if (sel == OS.sel_webView_windowScriptObjectAvailable_) { webKit.webView_windowScriptObjectAvailable (arg0, arg1); } else if (sel == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage) { return webKit.callRunBeforeUnloadConfirmPanelWithMessage (arg0, arg1).id; } return 0; } static long /*int*/ browserProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2) { Display d = Display.getCurrent(); if (d == null || d.isDisposed()) return 0; Widget widget = d.findWidget(id); if (widget == null) return 0; WebKit webKit = (WebKit)((Browser)widget).webBrowser; if (sel == OS.sel_webView_didFailProvisionalLoadWithError_forFrame_) { webKit.webView_didFailProvisionalLoadWithError_forFrame(arg0, arg1, arg2); } else if (sel == OS.sel_webView_didReceiveTitle_forFrame_) { webKit.webView_didReceiveTitle_forFrame(arg0, arg1, arg2); } else if (sel == OS.sel_webView_resource_didFinishLoadingFromDataSource_) { webKit.webView_resource_didFinishLoadingFromDataSource(arg0, arg1, arg2); } else if (sel == OS.sel_webView_identifierForInitialRequest_fromDataSource_) { return webKit.webView_identifierForInitialRequest_fromDataSource(arg0, arg1, arg2); } else if (sel == OS.sel_webView_contextMenuItemsForElement_defaultMenuItems_) { return webKit.webView_contextMenuItemsForElement_defaultMenuItems(arg0, arg1, arg2); } else if (sel == OS.sel_webView_mouseDidMoveOverElement_modifierFlags_) { webKit.webView_mouseDidMoveOverElement_modifierFlags(arg0, arg1, arg2); } else if (sel == OS.sel_webView_unableToImplementPolicyWithError_frame_) { webKit.webView_unableToImplementPolicyWithError_frame(arg0, arg1, arg2); } else if (sel == OS.sel_webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame_) { return webKit.webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame(arg0, arg1, arg2) ? 1 : 0; } else if (sel == OS.sel_webView_runJavaScriptAlertPanelWithMessage_initiatedByFrame_) { webKit.webView_runJavaScriptAlertPanelWithMessage(arg0, arg1); } else if (sel == OS.sel_webView_runJavaScriptConfirmPanelWithMessage_initiatedByFrame_) { return webKit.webView_runJavaScriptConfirmPanelWithMessage(arg0, arg1); } else if (sel == OS.sel_createPanelDidEnd) { webKit.createPanelDidEnd(arg0, arg1, arg2); } return 0; } static long /*int*/ browserProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ arg3) { Display d = Display.getCurrent(); if (d == null || d.isDisposed()) return 0; Widget widget = d.findWidget(id); if (widget == null) return 0; WebKit webKit = (WebKit)((Browser)widget).webBrowser; if (sel == OS.sel_webView_resource_didFailLoadingWithError_fromDataSource_) { webKit.webView_resource_didFailLoadingWithError_fromDataSource(arg0, arg1, arg2, arg3); } else if (sel == OS.sel_webView_resource_didReceiveAuthenticationChallenge_fromDataSource_) { webKit.webView_resource_didReceiveAuthenticationChallenge_fromDataSource(arg0, arg1, arg2, arg3); } else if (sel == OS.sel_callJava) { id result = webKit.callJava(arg0, arg1, arg2, arg3); return result == null ? 0 : result.id; } return 0; } static long /*int*/ browserProc(long /*int*/ id, long /*int*/ sel, long /*int*/ arg0, long /*int*/ arg1, long /*int*/ arg2, long /*int*/ arg3, long /*int*/ arg4) { Display d = Display.getCurrent(); if (d == null || d.isDisposed()) return 0; Widget widget = d.findWidget(id); if (widget == null) return 0; WebKit webKit = (WebKit)((Browser)widget).webBrowser; if (sel == OS.sel_webView_resource_willSendRequest_redirectResponse_fromDataSource_) { return webKit.webView_resource_willSendRequest_redirectResponse_fromDataSource(arg0, arg1, arg2, arg3, arg4); } else if (sel == OS.sel_webView_decidePolicyForMIMEType_request_frame_decisionListener_) { webKit.webView_decidePolicyForMIMEType_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4); } else if (sel == OS.sel_webView_decidePolicyForNavigationAction_request_frame_decisionListener_) { webKit.webView_decidePolicyForNavigationAction_request_frame_decisionListener(arg0, arg1, arg2, arg3, arg4); } else if (sel == OS.sel_webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener_) { webKit.webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(arg0, arg1, arg2, arg3, arg4); } return 0; } static boolean isSelectorExcludedFromWebScript (long /*int*/ aSelector) { return !(aSelector == OS.sel_callJava || aSelector == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage); } static long /*int*/ webScriptNameForSelector (long /*int*/ aSelector) { if (aSelector == OS.sel_callJava) { return NSString.stringWith ("callJava").id; //$NON-NLS-1$ } if (aSelector == OS.sel_callRunBeforeUnloadConfirmPanelWithMessage) { return NSString.stringWith ("callRunBeforeUnloadConfirmPanelWithMessage").id; //$NON-NLS-1$ } return 0; } @Override public boolean close () { return close (true); } boolean close (boolean showPrompters) { if (!jsEnabled) return true; String functionName = EXECUTE_ID + "CLOSE"; // $NON-NLS-1$ StringBuffer buffer = new StringBuffer ("function "); // $NON-NLS-1$ buffer.append (functionName); buffer.append ("(win) {\n"); // $NON-NLS-1$ buffer.append ("var fn = win.onbeforeunload; if (fn != null) {try {var str = fn(); "); // $NON-NLS-1$ if (showPrompters) { buffer.append ("if (str != null) { "); // $NON-NLS-1$ buffer.append ("var result = window.external.callRunBeforeUnloadConfirmPanelWithMessage(str);"); // $NON-NLS-1$ buffer.append ("if (!result) return false;}"); // $NON-NLS-1$ } buffer.append ("} catch (e) {}}"); // $NON-NLS-1$ buffer.append ("try {for (var i = 0; i < win.frames.length; i++) {var result = "); // $NON-NLS-1$ buffer.append (functionName); buffer.append ("(win.frames[i]); if (!result) return false;}} catch (e) {} return true;"); // $NON-NLS-1$ buffer.append ("\n};"); // $NON-NLS-1$ execute (buffer.toString ()); Boolean result = (Boolean)evaluate ("return " + functionName +"(window);"); // $NON-NLS-1$ // $NON-NLS-2$ if (result == null) return false; return result.booleanValue (); } @Override public boolean execute (String script) { WebFrame frame = webView.mainFrame(); long /*int*/ context = frame.globalContext(); byte[] bytes = (script + '\0').getBytes(StandardCharsets.UTF_8); //$NON-NLS-1$ long /*int*/ scriptString = OS.JSStringCreateWithUTF8CString(bytes); bytes = (getUrl() + '\0').getBytes(StandardCharsets.UTF_8); //$NON-NLS-1$ long /*int*/ urlString = OS.JSStringCreateWithUTF8CString(bytes); long /*int*/ result = OS.JSEvaluateScript(context, scriptString, 0, urlString, 0, null); OS.JSStringRelease(urlString); OS.JSStringRelease(scriptString); return result != 0; } @Override public boolean forward () { html = null; return webView.goForward(); } @Override public String getBrowserType () { return "webkit"; //$NON-NLS-1$ } @Override public String getText() { WebFrame mainFrame = webView.mainFrame(); WebDataSource dataSource = mainFrame.dataSource(); if (dataSource == null) return ""; //$NON-NLS-1$ WebDocumentRepresentation representation = dataSource.representation(); if (representation == null) return ""; //$NON-NLS-1$ NSString source = representation.documentSource(); if (source == null) return ""; //$NON-NLS-1$ return source.getString(); } @Override public String getUrl() { /* WebKit auto-navigates to about:blank at startup */ if (url.length() == 0) return ABOUT_BLANK; return url; } @Override public boolean isBackEnabled() { return webView.canGoBack(); } @Override public boolean isForwardEnabled() { return webView.canGoForward(); } @Override public void refresh() { html = null; webView.reload(null); } @Override public boolean setText(String html, boolean trusted) { /* * If this.html is not null then the about:blank page is already being loaded, * so no navigate is required. Just set the html that is to be shown. */ boolean blankLoading = this.html != null; this.html = html; untrustedText = !trusted; if (blankLoading) return true; NSURL inURL = NSURL.URLWithString(NSString.stringWith (ABOUT_BLANK)); NSURLRequest request = NSURLRequest.requestWithURL(inURL); WebFrame mainFrame = webView.mainFrame(); mainFrame.loadRequest(request); return true; } @Override public boolean setUrl(String url, String postData, String[] headers) { html = null; lastNavigateURL = url; if (url.indexOf('/') == 0) { url = PROTOCOL_FILE + url; } else if (url.indexOf(':') == -1) { url = PROTOCOL_HTTP + url; } NSString str = NSString.stringWith(url); NSString unescapedStr = NSString.stringWith("%#"); //$NON-NLS-1$ long /*int*/ ptr = OS.CFURLCreateStringByAddingPercentEscapes(0, str.id, unescapedStr.id, 0, OS.kCFStringEncodingUTF8); NSString escapedString = new NSString(ptr); NSURL inURL = NSURL.URLWithString(escapedString); OS.CFRelease(ptr); NSMutableURLRequest request = (NSMutableURLRequest)NSMutableURLRequest.requestWithURL(inURL); if (postData != null) { request.setHTTPMethod(NSString.stringWith(POST)); byte[] bytes = postData.getBytes(); NSData data = NSData.dataWithBytes(bytes, bytes.length); request.setHTTPBody(data); } if (headers != null) { for (int i = 0; i < headers.length; i++) { String current = headers[i]; if (current != null) { int index = current.indexOf(':'); if (index != -1) { String key = current.substring(0, index).trim(); String value = current.substring(index + 1).trim(); if (key.length() > 0 && value.length() > 0) { if (key.equalsIgnoreCase(USER_AGENT)) { /* * Feature of WebKit. The user-agent header value cannot be overridden * here. The workaround is to temporarily set the value on the WebView * and then remove it after the loading of the request has begun. */ webView.setCustomUserAgent(NSString.stringWith(value)); } else { request.setValue(NSString.stringWith(value), NSString.stringWith(key)); } } } } } } WebFrame mainFrame = webView.mainFrame(); mainFrame.loadRequest(request); webView.setCustomUserAgent(null); return true; } @Override public void stop() { html = null; webView.stopLoading(null); } @Override boolean translateMnemonics() { return false; } /* WebFrameLoadDelegate */ void webView_didChangeLocationWithinPageForFrame(long /*int*/ sender, long /*int*/ frameID) { WebFrame frame = new WebFrame(frameID); WebDataSource dataSource = frame.dataSource(); NSURLRequest request = dataSource.request(); NSURL url = request.URL(); NSString s = url.absoluteString(); int length = (int)/*64*/s.length(); if (length == 0) return; String url2 = s.getString(); /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (url2.equals (URI_FILEROOT)) { url2 = ABOUT_BLANK; } else { length = URI_FILEROOT.length (); if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') { url2 = ABOUT_BLANK + url2.substring (length); } } final Display display = browser.getDisplay(); boolean top = frameID == webView.mainFrame().id; if (top) { StatusTextEvent statusText = new StatusTextEvent(browser); statusText.display = display; statusText.widget = browser; statusText.text = url2; for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed(statusText); } } LocationEvent location = new LocationEvent(browser); location.display = display; location.widget = browser; location.location = url2; location.top = top; for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changed(location); } } void webView_didFailProvisionalLoadWithError_forFrame(long /*int*/ sender, long /*int*/ error, long /*int*/ frame) { if (frame == webView.mainFrame().id) { /* * Feature on WebKit. The identifier is used here as a marker for the events * related to the top frame and the URL changes related to that top frame as * they should appear on the location bar of a browser. It is expected to reset * the identifier to 0 when the event didFinishLoadingFromDataSource related to * the identifierForInitialRequest event is received. However, WebKit fires * the didFinishLoadingFromDataSource event before the entire content of the * top frame is loaded. It is possible to receive multiple willSendRequest * events in this interval, causing the Browser widget to send unwanted * Location.changing events. For this reason, the identifier is reset to 0 * when the top frame has either finished loading (didFinishLoadForFrame * event) or failed (didFailProvisionalLoadWithError). */ identifier = 0; } NSError nserror = new NSError(error); long /*int*/ errorCode = nserror.code(); if (OS.NSURLErrorBadURL < errorCode) return; NSURL failingURL = null; NSDictionary info = nserror.userInfo(); if (info != null) { id id = info.valueForKey(NSString.stringWith("NSErrorFailingURLKey")); //$NON-NLS-1$ if (id != null) failingURL = new NSURL(id); } if (failingURL != null && OS.NSURLErrorServerCertificateNotYetValid <= errorCode && errorCode <= OS.NSURLErrorSecureConnectionFailed) { /* handle invalid certificate error */ id certificates = info.objectForKey(NSString.stringWith("NSErrorPeerCertificateChainKey")); //$NON-NLS-1$ long /*int*/[] policySearch = new long /*int*/[1]; long /*int*/[] policyRef = new long /*int*/[1]; long /*int*/[] trustRef = new long /*int*/[1]; boolean success = false; int result = OS.SecPolicySearchCreate(OS.CSSM_CERT_X_509v3, 0, 0, policySearch); if (result == 0 && policySearch[0] != 0) { result = OS.SecPolicySearchCopyNext(policySearch[0], policyRef); if (result == 0 && policyRef[0] != 0) { result = OS.SecTrustCreateWithCertificates(certificates.id, policyRef[0], trustRef); if (result == 0 && trustRef[0] != 0) { SFCertificateTrustPanel panel = SFCertificateTrustPanel.sharedCertificateTrustPanel(); String failingUrlString = failingURL.absoluteString().getString(); String message = Compatibility.getMessage("SWT_InvalidCert_Message", new Object[] {failingUrlString}); //$NON-NLS-1$ panel.setAlternateButtonTitle(NSString.stringWith(Compatibility.getMessage("SWT_Cancel"))); //$NON-NLS-1$ panel.setShowsHelp(true); failingURL.retain(); NSWindow window = browser.getShell().view.window(); panel.beginSheetForWindow(window, delegate, OS.sel_createPanelDidEnd, failingURL.id, trustRef[0], NSString.stringWith(message)); success = true; } } } if (trustRef[0] != 0) OS.CFRelease(trustRef[0]); if (policyRef[0] != 0) OS.CFRelease(policyRef[0]); if (policySearch[0] != 0) OS.CFRelease(policySearch[0]); if (success) return; } /* handle other types of errors */ NSString description = nserror.localizedDescription(); if (description != null) { String descriptionString = description.getString(); String message = failingURL != null ? failingURL.absoluteString().getString() + "\n\n" : ""; //$NON-NLS-1$ //$NON-NLS-2$ message += Compatibility.getMessage ("SWT_Page_Load_Failed", new Object[] {descriptionString}); //$NON-NLS-1$ MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.ICON_ERROR); messageBox.setMessage(message); messageBox.open(); } } void createPanelDidEnd(long /*int*/ sheet, long /*int*/ returnCode, long /*int*/ contextInfo) { NSURL failingURL = new NSURL(contextInfo); failingURL.autorelease(); if (returnCode != OS.NSFileHandlingPanelOKButton) return; /* nothing more to do */ long /*int*/ method = OS.class_getClassMethod(OS.class_NSURLRequest, OS.sel_setAllowsAnyHTTPSCertificate); if (method != 0) { OS.objc_msgSend(OS.class_NSURLRequest, OS.sel_setAllowsAnyHTTPSCertificate, 1, failingURL.host().id); setUrl(failingURL.absoluteString().getString(), null, null); } } void webView_didFinishLoadForFrame(long /*int*/ sender, long /*int*/ frameID) { if (frameID == webView.mainFrame().id) { /* * If html is not null then there is html from a previous setText() call * waiting to be set into the about:blank page once it has completed loading. */ if (html != null) { if (getUrl().startsWith(ABOUT_BLANK)) { loadingText = true; NSString string = NSString.stringWith(html); NSString URLString; if (untrustedText) { URLString = NSString.stringWith(ABOUT_BLANK); } else { URLString = NSString.stringWith(URI_FILEROOT); } NSURL URL = NSURL.URLWithString(URLString); WebFrame mainFrame = webView.mainFrame(); mainFrame.loadHTMLString(string, URL); html = null; } } /* * The loadHTMLString() invocation above will trigger a second webView_didFinishLoadForFrame * callback when it is completed. If text was just set into the browser then wait for this * second callback to come before sending the title or completed events. */ if (!loadingText) { /* * To be consistent with other platforms a title event should be fired when a * page has completed loading. A page with a <title> tag will do this * automatically when the didReceiveTitle callback is received. However a page * without a <title> tag will not do this by default, so fire the event * here with the page's url as the title. */ Display display = browser.getDisplay(); WebFrame frame = new WebFrame(frameID); WebDataSource dataSource = frame.dataSource(); if (dataSource != null) { NSString title = dataSource.pageTitle(); if (title == null) { /* page has no title */ TitleEvent newEvent = new TitleEvent(browser); newEvent.display = display; newEvent.widget = browser; newEvent.title = getUrl(); for (int i = 0; i < titleListeners.length; i++) { titleListeners[i].changed(newEvent); } if (browser.isDisposed()) return; } } ProgressEvent progress = new ProgressEvent(browser); progress.display = display; progress.widget = browser; progress.current = MAX_PROGRESS; progress.total = MAX_PROGRESS; for (int i = 0; i < progressListeners.length; i++) { progressListeners[i].completed(progress); } } loadingText = false; if (browser.isDisposed()) return; /* * Feature on WebKit. The identifier is used here as a marker for the events * related to the top frame and the URL changes related to that top frame as * they should appear on the location bar of a browser. It is expected to reset * the identifier to 0 when the event didFinishLoadingFromDataSource related to * the identifierForInitialRequest event is received. However, WebKit fires * the didFinishLoadingFromDataSource event before the entire content of the * top frame is loaded. It is possible to receive multiple willSendRequest * events in this interval, causing the Browser widget to send unwanted * Location.changing events. For this reason, the identifier is reset to 0 * when the top frame has either finished loading (didFinishLoadForFrame * event) or failed (didFailProvisionalLoadWithError). */ identifier = 0; } } void hookDOMKeyListeners(long /*int*/ frameID) { WebFrame frame = new WebFrame(frameID); DOMDocument document = frame.DOMDocument(); if (document == null) return; NSString type = NSString.stringWith(DOMEVENT_KEYDOWN); document.addEventListener(type, delegate, false); type = NSString.stringWith(DOMEVENT_KEYUP); document.addEventListener(type, delegate, false); } void hookDOMMouseListeners(long /*int*/ frameID) { WebFrame frame = new WebFrame(frameID); DOMDocument document = frame.DOMDocument(); if (document == null) return; NSString type = NSString.stringWith(DOMEVENT_MOUSEDOWN); document.addEventListener(type, delegate, false); type = NSString.stringWith(DOMEVENT_MOUSEUP); document.addEventListener(type, delegate, false); type = NSString.stringWith(DOMEVENT_MOUSEMOVE); document.addEventListener(type, delegate, false); type = NSString.stringWith(DOMEVENT_MOUSEWHEEL); document.addEventListener(type, delegate, false); } void webView_didReceiveTitle_forFrame(long /*int*/ sender, long /*int*/ titleID, long /*int*/ frameID) { if (frameID == webView.mainFrame().id) { NSString title = new NSString(titleID); String newTitle = title.getString(); TitleEvent newEvent = new TitleEvent(browser); newEvent.display = browser.getDisplay(); newEvent.widget = browser; newEvent.title = newTitle; for (int i = 0; i < titleListeners.length; i++) { titleListeners[i].changed(newEvent); } } } void webView_didStartProvisionalLoadForFrame(long /*int*/ sender, long /*int*/ frameID) { /* * This code is intentionally commented. WebFrameLoadDelegate:didStartProvisionalLoadForFrame is * called before WebResourceLoadDelegate:willSendRequest and * WebFrameLoadDelegate:didCommitLoadForFrame. The resource count is reset when didCommitLoadForFrame * is received for the top frame. */ // if (frameID == webView.mainFrame().id) { // /* reset resource status variables */ // resourceCount= 0; // } } void webView_didCommitLoadForFrame(long /*int*/ sender, long /*int*/ frameID) { WebFrame frame = new WebFrame(frameID); WebDataSource dataSource = frame.dataSource(); NSURLRequest request = dataSource.request(); NSURL url = request.URL(); NSString s = url.absoluteString(); int length = (int)/*64*/s.length(); if (length == 0) return; String url2 = s.getString(); /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (url2.equals (URI_FILEROOT)) { url2 = ABOUT_BLANK; } else { length = URI_FILEROOT.length (); if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') { url2 = ABOUT_BLANK + url2.substring (length); } } Display display = browser.getDisplay(); boolean top = frameID == webView.mainFrame().id; if (top) { /* reset resource status variables */ resourceCount = 0; this.url = url2; /* * Each invocation of setText() causes webView_didCommitLoadForFrame to be invoked * twice, once for the initial navigate to about:blank, and once for the auto-navigate * to about:blank that WebKit does when loadHTMLString is invoked. If this is the * first webView_didCommitLoadForFrame callback received for a setText() invocation * then do not send any events or re-install registered BrowserFunctions. */ if (url2.startsWith(ABOUT_BLANK) && html != null) return; /* re-install registered functions */ Iterator<BrowserFunction> elements = functions.values().iterator (); while (elements.hasNext ()) { BrowserFunction function = elements.next (); execute (function.functionString); } ProgressEvent progress = new ProgressEvent(browser); progress.display = display; progress.widget = browser; progress.current = 1; progress.total = MAX_PROGRESS; for (int i = 0; i < progressListeners.length; i++) { progressListeners[i].changed(progress); } if (browser.isDisposed()) return; StatusTextEvent statusText = new StatusTextEvent(browser); statusText.display = display; statusText.widget = browser; statusText.text = url2; for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed(statusText); } if (browser.isDisposed()) return; hookDOMKeyListeners(frameID); } hookDOMMouseListeners(frameID); LocationEvent location = new LocationEvent(browser); location.display = display; location.widget = browser; location.location = url2; location.top = top; for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changed(location); } } void webView_windowScriptObjectAvailable (long /*int*/ webView, long /*int*/ windowScriptObject) { NSObject scriptObject = new NSObject (windowScriptObject); NSString key = NSString.stringWith ("external"); //$NON-NLS-1$ scriptObject.setValue (delegate, key); } /* WebResourceLoadDelegate */ void webView_resource_didFinishLoadingFromDataSource(long /*int*/ sender, long /*int*/ identifier, long /*int*/ dataSource) { /* * Feature on WebKit. The identifier is used here as a marker for the events * related to the top frame and the URL changes related to that top frame as * they should appear on the location bar of a browser. It is expected to reset * the identifier to 0 when the event didFinishLoadingFromDataSource related to * the identifierForInitialRequest event is received. However, WebKit fires * the didFinishLoadingFromDataSource event before the entire content of the * top frame is loaded. It is possible to receive multiple willSendRequest * events in this interval, causing the Browser widget to send unwanted * Location.changing events. For this reason, the identifier is reset to 0 * when the top frame has either finished loading (didFinishLoadForFrame * event) or failed (didFailProvisionalLoadWithError). */ // this code is intentionally commented //if (this.identifier == identifier) this.identifier = 0; } void webView_resource_didFailLoadingWithError_fromDataSource(long /*int*/ sender, long /*int*/ identifier, long /*int*/ error, long /*int*/ dataSource) { /* * Feature on WebKit. The identifier is used here as a marker for the events * related to the top frame and the URL changes related to that top frame as * they should appear on the location bar of a browser. It is expected to reset * the identifier to 0 when the event didFinishLoadingFromDataSource related to * the identifierForInitialRequest event is received. However, WebKit fires * the didFinishLoadingFromDataSource event before the entire content of the * top frame is loaded. It is possible to receive multiple willSendRequest * events in this interval, causing the Browser widget to send unwanted * Location.changing events. For this reason, the identifier is reset to 0 * when the top frame has either finished loading (didFinishLoadForFrame * event) or failed (didFailProvisionalLoadWithError). */ // this code is intentionally commented //if (this.identifier == identifier) this.identifier = 0; } void webView_resource_didReceiveAuthenticationChallenge_fromDataSource (long /*int*/ sender, long /*int*/ identifier, long /*int*/ challenge, long /*int*/ dataSource) { NSURLAuthenticationChallenge nsChallenge = new NSURLAuthenticationChallenge (challenge); /* * Do not invoke the listeners if this challenge has been failed too many * times because a listener is likely giving incorrect credentials repeatedly * and will do so indefinitely. */ if (nsChallenge.previousFailureCount () < 3) { for (int i = 0; i < authenticationListeners.length; i++) { AuthenticationEvent event = new AuthenticationEvent (browser); event.location = lastNavigateURL; authenticationListeners[i].authenticate (event); if (!event.doit) { id challengeSender = nsChallenge.sender (); OS.objc_msgSend (challengeSender.id, OS.sel_cancelAuthenticationChallenge_, challenge); return; } if (event.user != null && event.password != null) { id challengeSender = nsChallenge.sender (); NSString user = NSString.stringWith (event.user); NSString password = NSString.stringWith (event.password); NSURLCredential credential = NSURLCredential.credentialWithUser (user, password, OS.NSURLCredentialPersistenceForSession); OS.objc_msgSend (challengeSender.id, OS.sel_useCredential_forAuthenticationChallenge_, credential.id, challenge); return; } } } /* no listener handled the challenge, so try to invoke the native panel */ long /*int*/ cls = OS.class_WebPanelAuthenticationHandler; if (cls != 0) { long /*int*/ method = OS.class_getClassMethod (cls, OS.sel_sharedHandler); if (method != 0) { long /*int*/ handler = OS.objc_msgSend (cls, OS.sel_sharedHandler); if (handler != 0) { OS.objc_msgSend (handler, OS.sel_startAuthentication, challenge, webView.window ().id); return; } } } /* the native panel was not available, so show a custom dialog */ String[] userReturn = new String[1], passwordReturn = new String[1]; NSURLCredential proposedCredential = nsChallenge.proposedCredential (); if (proposedCredential != null) { userReturn[0] = proposedCredential.user ().getString (); if (proposedCredential.hasPassword ()) { passwordReturn[0] = proposedCredential.password ().getString (); } } NSURLProtectionSpace space = nsChallenge.protectionSpace (); String host = space.host ().getString () + ':' + space.port (); String realm = space.realm ().getString (); boolean result = showAuthenticationDialog (userReturn, passwordReturn, host, realm); if (!result) { id challengeSender = nsChallenge.sender (); OS.objc_msgSend (challengeSender.id, OS.sel_cancelAuthenticationChallenge_, challenge); return; } id challengeSender = nsChallenge.sender (); NSString user = NSString.stringWith (userReturn[0]); NSString password = NSString.stringWith (passwordReturn[0]); NSURLCredential credential = NSURLCredential.credentialWithUser (user, password, OS.NSURLCredentialPersistenceForSession); OS.objc_msgSend (challengeSender.id, OS.sel_useCredential_forAuthenticationChallenge_, credential.id, challenge); } boolean showAuthenticationDialog (final String[] user, final String[] password, String host, String realm) { final Shell shell = new Shell (browser.getShell ()); shell.setLayout (new GridLayout ()); String title = SWT.getMessage ("SWT_Authentication_Required"); //$NON-NLS-1$ shell.setText (title); Label label = new Label (shell, SWT.WRAP); label.setText (Compatibility.getMessage ("SWT_Enter_Username_and_Password", new String[] {realm, host})); //$NON-NLS-1$ GridData data = new GridData (); Monitor monitor = browser.getMonitor (); int maxWidth = monitor.getBounds ().width * 2 / 3; int width = label.computeSize (SWT.DEFAULT, SWT.DEFAULT).x; data.widthHint = Math.min (width, maxWidth); data.horizontalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; label.setLayoutData (data); Label userLabel = new Label (shell, SWT.NONE); userLabel.setText (SWT.getMessage ("SWT_Username")); //$NON-NLS-1$ final Text userText = new Text (shell, SWT.BORDER); if (user[0] != null) userText.setText (user[0]); data = new GridData (); data.horizontalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; userText.setLayoutData (data); Label passwordLabel = new Label (shell, SWT.NONE); passwordLabel.setText (SWT.getMessage ("SWT_Password")); //$NON-NLS-1$ final Text passwordText = new Text (shell, SWT.PASSWORD | SWT.BORDER); if (password[0] != null) passwordText.setText (password[0]); data = new GridData (); data.horizontalAlignment = GridData.FILL; data.grabExcessHorizontalSpace = true; passwordText.setLayoutData (data); final boolean[] result = new boolean[1]; final Button[] buttons = new Button[2]; Listener listener = event -> { user[0] = userText.getText(); password[0] = passwordText.getText(); result[0] = event.widget == buttons[1]; shell.close(); }; Composite composite = new Composite (shell, SWT.NONE); data = new GridData (); data.horizontalAlignment = GridData.END; composite.setLayoutData (data); composite.setLayout (new GridLayout (2, true)); buttons[0] = new Button (composite, SWT.PUSH); buttons[0].setText (SWT.getMessage("SWT_Cancel")); //$NON-NLS-1$ buttons[0].setLayoutData (new GridData (GridData.FILL_HORIZONTAL)); buttons[0].addListener (SWT.Selection, listener); buttons[1] = new Button (composite, SWT.PUSH); buttons[1].setText (SWT.getMessage("SWT_OK")); //$NON-NLS-1$ buttons[1].setLayoutData (new GridData (GridData.FILL_HORIZONTAL)); buttons[1].addListener (SWT.Selection, listener); shell.setDefaultButton (buttons[1]); shell.pack (); shell.open (); Display display = browser.getDisplay (); while (!shell.isDisposed ()) { if (!display.readAndDispatch ()) display.sleep (); } return result[0]; } long /*int*/ webView_identifierForInitialRequest_fromDataSource(long /*int*/ sender, long /*int*/ request, long /*int*/ dataSourceID) { ProgressEvent progress = new ProgressEvent(browser); progress.display = browser.getDisplay(); progress.widget = browser; progress.current = resourceCount; progress.total = Math.max(resourceCount, MAX_PROGRESS); for (int i = 0; i < progressListeners.length; i++) { progressListeners[i].changed(progress); } if (browser.isDisposed()) return 0; NSNumber identifier = NSNumber.numberWithInt(resourceCount++); if (this.identifier == 0) { WebDataSource dataSource = new WebDataSource(dataSourceID); WebFrame frame = dataSource.webFrame(); if (frame.id == webView.mainFrame().id) this.identifier = identifier.id; } return identifier.id; } long /*int*/ webView_resource_willSendRequest_redirectResponse_fromDataSource(long /*int*/ sender, long /*int*/ identifier, long /*int*/ request, long /*int*/ redirectResponse, long /*int*/ dataSource) { NSURLRequest nsRequest = new NSURLRequest (request); NSURL url = nsRequest.URL (); if (url.isFileURL ()) { NSMutableURLRequest newRequest = new NSMutableURLRequest (nsRequest.mutableCopy ()); newRequest.autorelease (); newRequest.setCachePolicy (OS.NSURLRequestReloadIgnoringLocalCacheData); return newRequest.id; } return request; } /* UIDelegate */ long /*int*/ webView_createWebViewWithRequest(long /*int*/ sender, long /*int*/ request) { WindowEvent newEvent = new WindowEvent(browser); newEvent.display = browser.getDisplay(); newEvent.widget = browser; newEvent.required = true; if (openWindowListeners != null) { for (int i = 0; i < openWindowListeners.length; i++) { openWindowListeners[i].open(newEvent); } } WebView result = null; Browser browser = null; if (newEvent.browser != null && newEvent.browser.webBrowser instanceof WebKit) { browser = newEvent.browser; } if (browser != null && !browser.isDisposed()) { result = ((WebKit)browser.webBrowser).webView; if (request != 0) { WebFrame mainFrame = result.mainFrame(); mainFrame.loadRequest(new NSURLRequest(request)); } } return result != null ? result.id : 0; } void webViewShow(long /*int*/ sender) { /* * Feature on WebKit. WebKit expects the application to * create a new Window using the Objective C Cocoa API in response * to UIDelegate.createWebViewWithRequest. The application is then * expected to use Objective C Cocoa API to make this window visible * when receiving the UIDelegate.webViewShow message. For some reason, * a window created with the Carbon API hosting the new browser instance * does not redraw until it has been resized. The fix is to increase the * size of the Shell and restore it to its initial size. */ Shell parent = browser.getShell(); Point pt = parent.getSize(); parent.setSize(pt.x+1, pt.y); parent.setSize(pt.x, pt.y); WindowEvent newEvent = new WindowEvent(browser); newEvent.display = browser.getDisplay(); newEvent.widget = browser; if (location != null) newEvent.location = location; if (size != null) newEvent.size = size; /* * Feature in WebKit. WebKit's tool bar contains * the address bar. The address bar is displayed * if the tool bar is displayed. There is no separate * notification for the address bar. * * Feature of OSX. The menu bar is always displayed. * There is no notification to hide the menu bar. */ newEvent.addressBar = toolBar; newEvent.menuBar = true; newEvent.statusBar = statusBar; newEvent.toolBar = toolBar; for (int i = 0; i < visibilityWindowListeners.length; i++) { visibilityWindowListeners[i].show(newEvent); } location = null; size = null; } void webView_setFrame(long /*int*/ sender, long /*int*/ frame) { NSRect rect = new NSRect(); OS.memmove(rect, frame, NSRect.sizeof); /* convert to SWT system coordinates */ Rectangle bounds = browser.getDisplay().getBounds(); location = new Point((int)rect.x, bounds.height - (int)rect.y - (int)rect.height); size = new Point((int)rect.width, (int)rect.height); } void webViewFocus(long /*int*/ sender) { } void webViewUnfocus(long /*int*/ sender) { } NSNumber callRunBeforeUnloadConfirmPanelWithMessage(long /*int*/ messageID, long /*int*/ arg) { boolean result = webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame (0, messageID, 0); return NSNumber.numberWithBool (result); } boolean webView_runBeforeUnloadConfirmPanelWithMessage_initiatedByFrame(long /*int*/ sender, long /*int*/ messageID, long /*int*/ frame) { NSString message = new NSString(messageID); StringBuffer text = new StringBuffer(Compatibility.getMessage("SWT_OnBeforeUnload_Message1")); //$NON-NLS-1$ text.append("\n\n"); //$NON-NLS-1$ text.append(message.getString()); text.append("\n\n"); //$NON-NLS-1$ text.append(Compatibility.getMessage("SWT_OnBeforeUnload_Message2")); //$NON-NLS-1$ MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.CANCEL | SWT.ICON_QUESTION | SWT.SHEET); messageBox.setMessage(text.toString()); return messageBox.open() == SWT.OK; } void webView_runJavaScriptAlertPanelWithMessage(long /*int*/ sender, long /*int*/ messageID) { NSString message = new NSString(messageID); String text = message.getString(); MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.ICON_WARNING); messageBox.setText("Javascript"); //$NON-NLS-1$ messageBox.setMessage(text); messageBox.open(); } int webView_runJavaScriptConfirmPanelWithMessage(long /*int*/ sender, long /*int*/ messageID) { NSString message = new NSString(messageID); String text = message.getString(); MessageBox messageBox = new MessageBox(browser.getShell(), SWT.OK | SWT.CANCEL | SWT.ICON_QUESTION); messageBox.setText("Javascript"); //$NON-NLS-1$ messageBox.setMessage(text); return messageBox.open() == SWT.OK ? 1 : 0; } void webView_runOpenPanelForFileButtonWithResultListener(long /*int*/ sender, long /*int*/ resultListenerID) { FileDialog dialog = new FileDialog(browser.getShell(), SWT.NONE); String result = dialog.open(); WebOpenPanelResultListener resultListener = new WebOpenPanelResultListener(resultListenerID); if (result == null) { resultListener.cancel(); return; } resultListener.chooseFilename(NSString.stringWith(result)); } void webViewClose(long /*int*/ sender) { Shell parent = browser.getShell(); WindowEvent newEvent = new WindowEvent(browser); newEvent.display = browser.getDisplay(); newEvent.widget = browser; for (int i = 0; i < closeWindowListeners.length; i++) { closeWindowListeners[i].close(newEvent); } browser.dispose(); if (parent.isDisposed()) return; /* * Feature on WebKit. WebKit expects the application to * create a new Window using the Objective C Cocoa API in response * to UIDelegate.createWebViewWithRequest. The application is then * expected to use Objective C Cocoa API to make this window visible * when receiving the UIDelegate.webViewShow message. For some reason, * a window created with the Carbon API hosting the new browser instance * does not redraw until it has been resized. The fix is to increase the * size of the Shell and restore it to its initial size. */ Point pt = parent.getSize(); parent.setSize(pt.x+1, pt.y); parent.setSize(pt.x, pt.y); } long /*int*/ webView_contextMenuItemsForElement_defaultMenuItems(long /*int*/ sender, long /*int*/ element, long /*int*/ defaultMenuItems) { Point pt = browser.getDisplay().getCursorLocation(); Event event = new Event(); event.x = pt.x; event.y = pt.y; browser.notifyListeners(SWT.MenuDetect, event); Menu menu = browser.getMenu(); if (!event.doit) return 0; if (menu != null && !menu.isDisposed()) { if (event.x != pt.x || event.y != pt.y) { menu.setLocation(event.x, event.y); } menu.setVisible(true); return 0; } return defaultMenuItems; } void webView_setStatusBarVisible(long /*int*/ sender, boolean visible) { /* Note. Webkit only emits the notification when the status bar should be hidden. */ statusBar = visible; } void webView_setStatusText(long /*int*/ sender, long /*int*/ textID) { NSString text = new NSString(textID); int length = (int)/*64*/text.length(); if (length == 0) return; StatusTextEvent statusText = new StatusTextEvent(browser); statusText.display = browser.getDisplay(); statusText.widget = browser; statusText.text = text.getString(); for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed(statusText); } } void webView_setResizable(long /*int*/ sender, boolean visible) { } void webView_setToolbarsVisible(long /*int*/ sender, boolean visible) { /* Note. Webkit only emits the notification when the tool bar should be hidden. */ toolBar = visible; } void webView_mouseDidMoveOverElement_modifierFlags (long /*int*/ sender, long /*int*/ elementInformationID, long /*int*/ modifierFlags) { if (elementInformationID == 0) return; NSString key = NSString.stringWith(WebElementLinkURLKey); NSDictionary elementInformation = new NSDictionary(elementInformationID); id value = elementInformation.valueForKey(key); if (value == null) { /* not currently over a link */ if (lastHoveredLinkURL == null) return; lastHoveredLinkURL = null; StatusTextEvent statusText = new StatusTextEvent(browser); statusText.display = browser.getDisplay(); statusText.widget = browser; statusText.text = ""; //$NON-NLS-1$ for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed(statusText); } return; } NSString url = new NSURL(value.id).absoluteString(); int length = (int)/*64*/url.length(); String urlString; if (length == 0) { urlString = ""; //$NON-NLS-1$ } else { urlString = url.getString(); } if (urlString.equals(lastHoveredLinkURL)) return; lastHoveredLinkURL = urlString; StatusTextEvent statusText = new StatusTextEvent(browser); statusText.display = browser.getDisplay(); statusText.widget = browser; statusText.text = urlString; for (int i = 0; i < statusTextListeners.length; i++) { statusTextListeners[i].changed(statusText); } } void webView_printFrameView (long /*int*/ sender, long /*int*/ frameViewID) { WebFrameView view = new WebFrameView(frameViewID); boolean viewPrint = view.documentViewShouldHandlePrint(); if (viewPrint) { view.printDocumentView(); return; } NSPrintInfo info = NSPrintInfo.sharedPrintInfo(); NSPrintOperation operation = view.printOperationWithPrintInfo(info); if (operation != null) operation.runOperation(); } /* PolicyDelegate */ void webView_decidePolicyForMIMEType_request_frame_decisionListener(long /*int*/ sender, long /*int*/ type, long /*int*/ request, long /*int*/ frame, long /*int*/ listenerID) { boolean canShow = WebView.canShowMIMEType(new NSString(type)); WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); if (canShow) { listener.use(); } else { listener.download(); } } void webView_decidePolicyForNavigationAction_request_frame_decisionListener(long /*int*/ sender, long /*int*/ actionInformation, long /*int*/ request, long /*int*/ frame, long /*int*/ listenerID) { NSURL url = new NSURLRequest(request).URL(); WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); if (loadingText) { /* * WebKit is auto-navigating to about:blank in response to a loadHTMLString() * invocation. This navigate should always proceed without sending an event * since it is preceded by an explicit navigate to about:blank in setText(). */ listener.use(); return; } if (url == null) { /* indicates that a URL with an invalid format was specified */ listener.ignore(); return; } if (url.isFileURL() && getUrl().startsWith(ABOUT_BLANK) && untrustedText) { /* indicates an attempt to access the local file system from untrusted content */ listener.ignore(); return; } NSString s = url.absoluteString(); String url2 = s.getString(); /* * If the URI indicates that the page is being rendered from memory * (via setText()) then set it to about:blank to be consistent with IE. */ if (url2.equals (URI_FILEROOT)) { url2 = ABOUT_BLANK; } else { int length = URI_FILEROOT.length (); if (url2.startsWith (URI_FILEROOT) && url2.charAt (length) == '#') { url2 = ABOUT_BLANK + url2.substring (length); } } LocationEvent newEvent = new LocationEvent(browser); newEvent.display = browser.getDisplay(); newEvent.widget = browser; newEvent.location = url2; newEvent.doit = true; if (locationListeners != null) { for (int i = 0; i < locationListeners.length; i++) { locationListeners[i].changing(newEvent); } } if (newEvent.doit) { if (jsEnabled != jsEnabledOnNextPage) { jsEnabled = jsEnabledOnNextPage; if (preferences == null) { preferences = (WebPreferences)new WebPreferences ().alloc ().init (); webView.setPreferences (preferences); } preferences.setJavaScriptEnabled (jsEnabled); } listener.use(); lastNavigateURL = url2; } else { listener.ignore(); } } void webView_decidePolicyForNewWindowAction_request_newFrameName_decisionListener(long /*int*/ sender, long /*int*/ actionInformation, long /*int*/ request, long /*int*/ frameName, long /*int*/ listenerID) { WebPolicyDecisionListener listener = new WebPolicyDecisionListener(listenerID); listener.use(); } void webView_unableToImplementPolicyWithError_frame(long /*int*/ sender, long /*int*/ error, long /*int*/ frame) { } /* WebDownload */ void download_decideDestinationWithSuggestedFilename(long /*int*/ downloadId, long /*int*/ filename) { NSString string = new NSString(filename); String name = string.getString(); FileDialog dialog = new FileDialog(browser.getShell(), SWT.SAVE); dialog.setText(SWT.getMessage ("SWT_FileDownload")); //$NON-NLS-1$ dialog.setFileName(name); String path = dialog.open(); NSURLDownload download = new NSURLDownload(downloadId); if (path == null) { /* cancel pressed */ download.cancel(); return; } download.setDestination(NSString.stringWith(path), true); } /* DOMEventListener */ void handleEvent(long /*int*/ evtId) { NSString string = new NSString(OS.objc_msgSend(evtId, OS.sel_type)); String type = string.getString(); if (DOMEVENT_KEYDOWN.equals(type) || DOMEVENT_KEYUP.equals(type)) { DOMKeyboardEvent event = new DOMKeyboardEvent(evtId); boolean ctrl = event.ctrlKey(); boolean shift = event.shiftKey(); boolean alt = event.altKey(); boolean meta = event.metaKey(); int keyCode = event.keyCode(); int charCode = event.charCode(); Event keyEvent = new Event(); keyEvent.widget = browser; int eventType = DOMEVENT_KEYDOWN.equals(type) ? SWT.KeyDown : SWT.KeyUp; keyEvent.type = eventType; int translatedKey = translateKey (keyCode); keyEvent.keyCode = translatedKey; keyEvent.character = (char)charCode; int stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0); keyEvent.stateMask = stateMask; boolean doit = true; if (keyEvent.type == SWT.KeyDown) { doit = sendKeyEvent(keyEvent); } else { browser.notifyListeners(keyEvent.type, keyEvent); doit = keyEvent.doit; } if (!doit) { event.preventDefault(); } else { if (eventType == SWT.KeyDown && stateMask == SWT.COMMAND) { if (translatedKey == 'v') { webView.paste (webView); event.preventDefault(); } else if (translatedKey == 'c') { webView.copy (webView); event.preventDefault(); } else if (translatedKey == 'x') { webView.cut (webView); event.preventDefault(); } } } return; } if (DOMEVENT_MOUSEWHEEL.equals(type)) { DOMWheelEvent event = new DOMWheelEvent(evtId); /* * The position of mouse events is received in screen-relative coordinates * in order to handle pages with frames, since frames express their event * coordinates relative to themselves rather than relative to their top- * level page. Convert screen-relative coordinates to be browser-relative. */ int screenX = event.screenX(); int screenY = event.screenY(); Point position = new Point(screenX, screenY); position = browser.getDisplay().map(null, browser, position); int delta = event.wheelDelta(); boolean ctrl = event.ctrlKey(); boolean shift = event.shiftKey(); boolean alt = event.altKey(); boolean meta = event.metaKey(); Event mouseEvent = new Event(); mouseEvent.type = SWT.MouseWheel; mouseEvent.widget = browser; mouseEvent.x = position.x; mouseEvent.y = position.y; mouseEvent.count = delta / 120; mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0); browser.notifyListeners (mouseEvent.type, mouseEvent); return; } /* mouse event */ DOMMouseEvent event = new DOMMouseEvent(evtId); /* * The position of mouse events is received in screen-relative coordinates * in order to handle pages with frames, since frames express their event * coordinates relative to themselves rather than relative to their top- * level page. Convert screen-relative coordinates to be browser-relative. */ int screenX = event.screenX(); int screenY = event.screenY(); Point position = new Point(screenX, screenY); position = browser.getDisplay().map(null, browser, position); int detail = event.detail(); int button = event.button(); boolean ctrl = event.ctrlKey(); boolean shift = event.shiftKey(); boolean alt = event.altKey(); boolean meta = event.metaKey(); Event mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = position.x; mouseEvent.y = position.y; mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0); if (DOMEVENT_MOUSEDOWN.equals (type)) { mouseEvent.type = SWT.MouseDown; mouseEvent.button = button + 1; mouseEvent.count = detail; } else if (DOMEVENT_MOUSEUP.equals (type)) { mouseEvent.type = SWT.MouseUp; mouseEvent.button = button + 1; mouseEvent.count = detail; switch (mouseEvent.button) { case 1: mouseEvent.stateMask |= SWT.BUTTON1; break; case 2: mouseEvent.stateMask |= SWT.BUTTON2; break; case 3: mouseEvent.stateMask |= SWT.BUTTON3; break; case 4: mouseEvent.stateMask |= SWT.BUTTON4; break; case 5: mouseEvent.stateMask |= SWT.BUTTON5; break; } } else if (DOMEVENT_MOUSEMOVE.equals (type)) { /* * Bug in WebKit. Spurious and redundant mousemove events are received in * various contexts, including following every MouseUp. The workaround is * to not fire MouseMove events whose x and y values match the last MouseMove */ if (mouseEvent.x == lastMouseMoveX && mouseEvent.y == lastMouseMoveY) return; mouseEvent.type = SWT.MouseMove; lastMouseMoveX = mouseEvent.x; lastMouseMoveY = mouseEvent.y; } browser.notifyListeners (mouseEvent.type, mouseEvent); if (detail == 2 && DOMEVENT_MOUSEDOWN.equals (type)) { mouseEvent = new Event (); mouseEvent.widget = browser; mouseEvent.x = position.x; mouseEvent.y = position.y; mouseEvent.stateMask = (alt ? SWT.ALT : 0) | (ctrl ? SWT.CTRL : 0) | (shift ? SWT.SHIFT : 0) | (meta ? SWT.COMMAND : 0); mouseEvent.type = SWT.MouseDoubleClick; mouseEvent.button = button + 1; mouseEvent.count = detail; browser.notifyListeners (mouseEvent.type, mouseEvent); } } /* external */ Object convertToJava (long /*int*/ value) { NSObject object = new NSObject (value); long /*int*/ clazz = OS.objc_lookUpClass ("NSString"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { NSString string = new NSString (value); return string.getString (); } clazz = OS.objc_lookUpClass ("NSNumber"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { NSNumber number = new NSNumber (value); long /*int*/ ptr = number.objCType (); byte[] type = new byte[1]; OS.memmove (type, ptr, 1); if (type[0] == 'c' || type[0] == 'B') { return new Boolean (number.boolValue ()); } if ("islqISLQfd".indexOf (type[0]) != -1) { //$NON-NLS-1$ return new Double (number.doubleValue ()); } } clazz = OS.objc_lookUpClass ("WebScriptObject"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { WebScriptObject script = new WebScriptObject (value); id id = script.valueForKey (NSString.stringWith ("length")); //$NON-NLS-1$ if (id == null) { /* not a JS array */ SWT.error (SWT.ERROR_INVALID_ARGUMENT); } int length = new NSNumber (id).intValue (); Object[] arguments = new Object[length]; for (int i = 0; i < length; i++) { id current = script.webScriptValueAtIndex (i); if (current != null) { arguments[i] = convertToJava (current.id); } } return arguments; } clazz = OS.objc_lookUpClass ("WebUndefined"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { return null; } SWT.error (SWT.ERROR_INVALID_ARGUMENT); return null; } NSObject convertToJS (Object value) { if (value == null) { long /*int*/ result = OS.objc_msgSend (OS.class_NSNull, OS.sel_null); return result != 0 ? new NSObject (result) : null; } if (value instanceof String) { return NSString.stringWith ((String)value); } if (value instanceof Boolean) { return NSNumber.numberWithBool (((Boolean)value).booleanValue ()); } if (value instanceof Number) { return NSNumber.numberWithDouble (((Number)value).doubleValue ()); } if (value instanceof Object[]) { Object[] arrayValue = (Object[]) value; int length = arrayValue.length; NSMutableArray array = NSMutableArray.arrayWithCapacity (length); for (int i = 0; i < length; i++) { Object currentObject = arrayValue[i]; array.addObject (convertToJS (currentObject)); } return array; } SWT.error (SWT.ERROR_INVALID_RETURN_VALUE); return null; } NSObject callJava (long /*int*/ index, long /*int*/ token, long /*int*/ args, long /*int*/ arg1) { Object returnValue = null; NSObject object = new NSObject (index); long /*int*/ clazz = OS.objc_lookUpClass ("NSNumber"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { NSNumber number = new NSNumber (index); Object key = new Integer (number.intValue ()); object = new NSObject (token); clazz = OS.objc_lookUpClass ("NSString"); //$NON-NLS-1$ if (object.isKindOfClass (clazz)) { NSString tokenString = new NSString (token); BrowserFunction function = (BrowserFunction)functions.get (key); if (function != null && tokenString.getString ().equals (function.token)) { try { Object temp = convertToJava (args); if (temp instanceof Object[]) { Object[] arguments = (Object[])temp; try { returnValue = function.function (arguments); } catch (Exception e) { /* exception during function invocation */ returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ()); } } } catch (IllegalArgumentException e) { /* invalid argument value type */ if (function.isEvaluate) { /* notify the evaluate function so that a java exception can be thrown */ function.function (new String[] {WebBrowser.CreateErrorString (new SWTException (SWT.ERROR_INVALID_RETURN_VALUE).getLocalizedMessage ())}); } returnValue = WebBrowser.CreateErrorString (e.getLocalizedMessage ()); } } } } try { return convertToJS (returnValue); } catch (SWTException e) { /* invalid return value type */ return convertToJS (WebBrowser.CreateErrorString (e.getLocalizedMessage ())); } } }